﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace WizzardTheGame
{
    class Object3D
    {
        private bool isVisible; 
        private Model model;
        private BoundingBox boundingBox;
        private Vector3 position;
        private Vector3 rotation;
        private float initial_y_rotation;
        private Vector3 velocity;
        private float scale;

        #region Properties

        public float Initial_y_rotation
        {
            get { return initial_y_rotation; }
            set { initial_y_rotation = value; }
        }

        public bool IsVisible { 
            get{return isVisible;}
            set{isVisible=value;} }
        
        public Model Model { 
            get{return model;}
            set{model = value;} }

        public Vector3 Position
        {
            get { return position; }
            set
            {
                position = value;
            }
        }

        public Vector3 Rotation { 
            get{return rotation;} 
            set{rotation = value;} }

        public Vector3 Velocity { 
            get{return velocity;}
            set{velocity=value;} }

        public float Scale { 
            get{return scale;} 
            set{scale = value;} }

        public BoundingBox BoundingBox
        {
            get
            {
                BoundingBox bb = TranslateBoundingBox(boundingBox);
                return bb;
            }
            private set { boundingBox = value; }
        }

	#endregion

        public Object3D(string modelPath):this()
        {
            LoadContent(modelPath);
        }

        public Object3D()
        {
            IsVisible = false;
            Scale = 1f;
            Position = Vector3.Zero;
            Rotation = Vector3.Zero;
            Velocity = Vector3.Zero;

        }

        public bool TestCollision(Object3D otherObject)
        {
            bool collision = false;
            BoundingBox b_this = BoundingBox;
            BoundingBox b_other = otherObject.BoundingBox;
            
            collision = b_this.Intersects(b_other);

            return collision;
        }

        //public void CreateBoundingBox()
        //{
        //    BoundingBox boundingBox = new BoundingBox();

        //    foreach (ModelMesh mesh in Model.Meshes)
        //    {
        //        VertexPositionNormalTexture[] vertices =
        //          new VertexPositionNormalTexture[mesh.VertexBuffer.SizeInBytes / VertexPositionNormalTexture.SizeInBytes];

        //        mesh.VertexBuffer.GetData<VertexPositionNormalTexture>(vertices);

        //        Vector3[] vertexs = new Vector3[vertices.Length];

        //        for (int index = 0; index < vertexs.Length; index++)
        //        {
        //            vertexs[index] = vertices[index].Position;
        //        }

        //        boundingBox = BoundingBox.CreateMerged(boundingBox,
        //          BoundingBox.CreateFromPoints(vertexs));
        //    }

        //    BoundingBox = boundingBox;
        //}

        public void CreateBoundingBox()
        {
            float minX, maxX, minY, maxY, minZ, maxZ;
            //minX = maxX = minY = maxY = minZ = maxZ = 0;

            minX = minY = minZ = float.MaxValue;
            maxX = maxY = maxZ = float.MinValue;

            foreach (ModelMesh mesh in Model.Meshes)
            {
                VertexPositionNormalTexture[] vertices =
                  new VertexPositionNormalTexture[mesh.VertexBuffer.SizeInBytes / VertexPositionNormalTexture.SizeInBytes];

                mesh.VertexBuffer.GetData<VertexPositionNormalTexture>(vertices);

                Vector3[] vertexs = new Vector3[vertices.Length];

                for (int index = 0; index < vertexs.Length; index++)
                {
                    if (vertices[index].Position.X < minX) minX = vertices[index].Position.X;
                    if (vertices[index].Position.X > maxX) maxX = vertices[index].Position.X;
                    if (vertices[index].Position.Y < minY) minY = vertices[index].Position.Y;
                    if (vertices[index].Position.Y > maxY) maxY = vertices[index].Position.Y;
                    if (vertices[index].Position.Z < minZ) minZ = vertices[index].Position.Z;
                    if (vertices[index].Position.Z > maxZ) maxZ = vertices[index].Position.Z;
                }
            }
            Vector3 min = new Vector3(minX-1f, minY-1f, minZ-1f);
            Vector3 max = new Vector3(maxX+1f, maxY+1f, maxZ+1f);
            BoundingBox = new BoundingBox(min, max);
        }

        public BoundingBox TranslateBoundingBox(BoundingBox boundingBox)
        {
            Matrix rotationMatrix = new Matrix();

            rotationMatrix += Matrix.CreateRotationX(Rotation.X);
            rotationMatrix += Matrix.CreateRotationY(Initial_y_rotation);
            rotationMatrix += Matrix.CreateRotationZ(Rotation.Z);

            boundingBox.Min = Vector3.Transform(boundingBox.Min, rotationMatrix * Matrix.CreateScale(Scale) * Matrix.CreateTranslation(Position));
            boundingBox.Max = Vector3.Transform(boundingBox.Max, rotationMatrix * Matrix.CreateScale(Scale) * Matrix.CreateTranslation(Position));

            return boundingBox;
        }

        public void Draw()
        {
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;

                    effect.World = Matrix.CreateFromYawPitchRoll(Rotation.Y, Rotation.X,
                        Rotation.Z) * Matrix.CreateScale(Scale) * Matrix.CreateTranslation(Position);

                    GameWorld gw = GameWorld.getInstance();
                    effect.Projection = gw.Camera.ProjectionMatrix;
                    effect.View = gw.Camera.ViewMatrix;
                }
                mesh.Draw();
            }
        }

        public void Move()
        {
        }

        public void LoadContent(string modelPath)
        {
            Model = GameWorld.getInstance().Content.Load<Model>(modelPath);
            CreateBoundingBox();
        }

    }
}